package com.minigame.card.paper.domain;

import com.minigame.card.domain.CardPlayer;
import com.minigame.card.enums.Direction;
import com.minigame.card.paper.enums.PaperCard;

import java.util.*;

import static cn.hutool.core.collection.CollUtil.countMap;
import static com.minigame.card.paper.util.PaperUtil.paperCardHu;
import static com.minigame.card.util.CardUtil.countPlayerCell;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;

public class PaperCardPlayer extends CardPlayer<PaperCard> {

    public boolean canHu() {
        int length = PaperCard.values().length;
        int[] counts = new int[length];
        Map<PaperCard, Integer> upCounts = countMap(up);
        for (int i = 0; i < length; i++) {
            Integer count = upCounts.get(PaperCard.indexOf(i));
            if (count != null) {
                counts[i] = count;
            }
        }
        return paperCardHu(counts);
    }

    public List<PaperCard> tryCh(PaperCard discard) {
        int index = discard.getIndex();
        int m = index % 3;
        int[] indexes = new int[3];
        boolean contains = false;
        switch (m) {
            case 0:
                indexes[0] = index;
                indexes[1] = index + 1;
                indexes[2] = index + 2;
                contains = up.contains(PaperCard.indexOf(indexes[1])) && up.contains(PaperCard.indexOf(indexes[2]));
                break;
            case 1:
                indexes[0] = index - 1;
                indexes[1] = index;
                indexes[2] = index + 1;
                contains = up.contains(PaperCard.indexOf(indexes[0])) && up.contains(PaperCard.indexOf(indexes[2]));
                break;
            case 2:
                indexes[0] = index - 2;
                indexes[1] = index - 1;
                indexes[2] = index;
                contains = up.contains(PaperCard.indexOf(indexes[0])) && up.contains(PaperCard.indexOf(indexes[1]));
                break;
        }
        if (contains) {
            return Arrays.stream(indexes).mapToObj(PaperCard::indexOf).collect(toList());
        }
        return emptyList();
    }

    @Override
    public Direction anticlockwiseNext(Direction rest) {
        Direction next = direction.anticlockwiseNext();
        while (next == rest) {
            next = next.anticlockwiseNext();
        }
        return next;
    }

    @Override
    public boolean requiredSelect(List<List<PaperCard>> options, PaperCard discard) {
        return false;
    }

    /**
     * 弃牌胡牌映射
     */
    public Map<PaperCard, List<PaperCard>> tingMap() {
        Map<PaperCard, List<PaperCard>> tingMap = new LinkedHashMap<>();
        int length = PaperCard.values().length;
        int[] upCounts = countPlayerCell(up, length, PaperCard::getIndex);
        List<PaperCard> disCardList = up.stream().distinct().collect(toList());
        for (PaperCard discard : disCardList) {
            List<PaperCard> huCards = new ArrayList<>();
            upCounts[discard.getIndex()]--;
            for (PaperCard card : PaperCard.values()) {
                upCounts[card.getIndex()]++;
                if (paperCardHu(Arrays.copyOf(upCounts, length))) {
                    huCards.add(card);
                }
                upCounts[card.getIndex()]--;
            }
            upCounts[discard.getIndex()]++;
            if (!huCards.isEmpty()) {
                tingMap.put(discard, huCards);
            }
        }
        return tingMap;
    }
}
